//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This is a sample for BCGControlBar Library Professional Edition
// Copyright (C) 1998-2016 BCGSoft Ltd.
// All rights reserved.
//
// This source code can be used, distributed or modified
// only under terms and conditions 
// of the accompanying license agreement.
//*******************************************************************************
//
// CChartHugeAverageDataView.cpp : implementation file
//

#include "stdafx.h"
#include "bcgpchartexample.h"
#include "ChartHugeAverageDataView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

const LPCTSTR lpszBoxDefaultLabel = _T("The Y Value indicator");

/////////////////////////////////////////////////////////////////////////////
// CChartHugeAverageDataView

IMPLEMENT_DYNCREATE(CChartHugeAverageDataView, CBCGPChartExampleView)

CChartHugeAverageDataView::CChartHugeAverageDataView()
	: CBCGPChartExampleView(CChartHugeAverageDataView::IDD)
{
	//{{AFX_DATA_INIT(CChartHugeAverageDataView)
	m_nDataPoints = 0;
	m_bZoom = TRUE;
	m_nZoomType = 0;
	m_nSelectionType = 0;
	m_strInfo = _T("");
	m_bShowScrollBar = TRUE;
	m_bInteractiveMode = FALSE;
	m_bScatterMode = FALSE;
	//}}AFX_DATA_INIT

	m_pValueBox = NULL;

	SetObjectColors();
}

CChartHugeAverageDataView::~CChartHugeAverageDataView()
{
}

void CChartHugeAverageDataView::SetObjectColors()
{
	m_brValueBoxText = CBCGPBrush(m_bIsDarkBackground ? CBCGPColor::DarkSlateBlue : CBCGPColor::SteelBlue);
	m_brValueBoxBorder = CBCGPBrush(CBCGPColor::SteelBlue, m_bIsDarkBackground ? .8 : .4);
	m_brValueBoxFill = CBCGPBrush(CBCGPColor::LightSteelBlue, CBCGPColor::White, CBCGPBrush::BCGP_GRADIENT_RADIAL_TOP, m_bIsDarkBackground ? .8 : .4);

	if (m_pValueBox != NULL)
	{
		m_pValueBox->m_format.m_brFillColor = m_brValueBoxFill;
		m_pValueBox->m_format.m_brTextColor = m_brValueBoxText;
		m_pValueBox->m_format.m_outlineFormat.m_brLineColor = m_brValueBoxBorder;
	}
}

void CChartHugeAverageDataView::DoDataExchange(CDataExchange* pDX)
{
	CBCGPChartExampleView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CChartHugeAverageDataView)
	DDX_Control(pDX, IDC_SHOW_SCROLLBARS, m_wndShowScrollBar);
	DDX_Control(pDX, IDC_SELECTION_LABEL, m_wndSelectionLabel);
	DDX_Control(pDX, IDC_ZOOM_100, m_wndZoom100);
	DDX_Control(pDX, IDC_SELECTION_TYPE, m_wndSelectionType);
	DDX_Control(pDX, IDC_ZOOM_TYPE, m_wndZoomType);
	DDX_Control(pDX, IDC_CHART, m_wndChart);
	DDX_CBIndex(pDX, IDC_DATA_POINTS, m_nDataPoints);
	DDX_Check(pDX, IDC_ZOOM, m_bZoom);
	DDX_CBIndex(pDX, IDC_ZOOM_TYPE, m_nZoomType);
	DDX_CBIndex(pDX, IDC_SELECTION_TYPE, m_nSelectionType);
	DDX_Text(pDX, IDC_INFO, m_strInfo);
	DDX_Check(pDX, IDC_SHOW_SCROLLBARS, m_bShowScrollBar);
	DDX_Check(pDX, IDC_INTERACTIVE_MODE, m_bInteractiveMode);
	DDX_Check(pDX, IDC_SCATTER_MODE, m_bScatterMode);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CChartHugeAverageDataView, CBCGPChartExampleView)
	//{{AFX_MSG_MAP(CChartHugeAverageDataView)
	ON_CBN_SELENDOK(IDC_DATA_POINTS, OnUpdateChart)
	ON_CBN_SELENDOK(IDC_ZOOM_TYPE, OnUpdateZoom)
	ON_BN_CLICKED(IDC_ZOOM_100, OnZoom100)
	ON_BN_CLICKED(IDC_SHOW_SCROLLBARS, OnUpdateScrollBars)
	ON_BN_CLICKED(IDC_INTERACTIVE_MODE, OnInteractiveMode)
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_ZOOM, OnUpdateZoom)
	ON_CBN_SELENDOK(IDC_SELECTION_TYPE, OnUpdateZoom)
	ON_BN_CLICKED(IDC_SCATTER_MODE, OnUpdateChart)
	//}}AFX_MSG_MAP
	ON_REGISTERED_MESSAGE(BCGM_ON_CHART_MOUSE_TRACK, OnMouseTrack)
	ON_REGISTERED_MESSAGE(BCGM_ON_CHART_AFTER_DRAW, OnAfterDraw)
	ON_REGISTERED_MESSAGE(BCGM_ON_CHART_AFTER_RECALC_LAYOUT, OnAfterRecalcLayout)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChartHugeAverageDataView diagnostics

#ifdef _DEBUG
void CChartHugeAverageDataView::AssertValid() const
{
	CBCGPChartExampleView::AssertValid();
}

void CChartHugeAverageDataView::Dump(CDumpContext& dc) const
{
	CBCGPChartExampleView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CChartHugeAverageDataView message handlers

void CChartHugeAverageDataView::OnInitialUpdate() 
{
	CBCGPChartExampleView::OnInitialUpdate();
	
	if (m_bIsReady)
	{
		return;
	}

	m_bIsReady = TRUE;

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	pChart->SetChartType(BCGPChartLongData);
	pChart->SetLegendPosition(BCGPChartLayout::LP_NONE);

	OnUpdateChart();
	OnUpdateZoom();

	CBCGPChartAxis* pYAxis = pChart->GetChartAxis(BCGP_CHART_Y_PRIMARY_AXIS);
	ASSERT_VALID(pYAxis);

	CBCGPChartAxis* pXAxis = pChart->GetChartAxis(BCGP_CHART_X_PRIMARY_AXIS);
	ASSERT_VALID(pXAxis);

	m_wndChart.SetFocus();

	m_pValueBox = new CBCGPChartTextObject(pChart, lpszBoxDefaultLabel, 80, 35, m_brValueBoxText, m_brValueBoxFill, m_brValueBoxBorder);
	m_pValueBox->SetCoordinates(80, 35, 200, 60, CBCGPChartObject::CM_PIXELS_FIXED_SIZE);
	
	m_pValueBox->m_format.m_textFormat = CBCGPTextFormat(
		_T("Arial"), 16., FW_REGULAR, CBCGPTextFormat::BCGP_FONT_STYLE_ITALIC);

	m_pValueBox->m_format.SetContentPadding(CBCGPSize(10., 10.));
	m_pValueBox->SetRoundedShape();
	m_pValueBox->SetShadow();

	pChart->AddChartObject(m_pValueBox);

	OnInteractiveMode();
}

void CChartHugeAverageDataView::OnUpdateChart() 
{
	CWaitCursor wait;

	UpdateData();

	int nDataPoints = 0;

	switch (m_nDataPoints)
	{
	case 0:
		nDataPoints = 1000;
		break;

	case 1:
		nDataPoints = 10000;
		break;

	case 2:
		nDataPoints = 100000;
		break;
	}

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	pChart->CleanUpChartData ();

	CBCGPChartLongSeries* pSeries = DYNAMIC_DOWNCAST(CBCGPChartLongSeries, pChart->GetSeries(0));
	if (pSeries != NULL)
	{
		pSeries->SetScatterMode(m_bScatterMode);
	}

	if (m_pValueBox != NULL)
	{
		m_pValueBox->m_strText = lpszBoxDefaultLabel;
	}

	double dblVal = 0;

	for (int i = 0; i < nDataPoints; i++)
	{
		double dblDelta = dblVal > 500 ? Rand(-500, 500) : Rand(0, 1000);
		dblVal += dblDelta;

		if (m_bScatterMode)
		{
			pChart->AddChartDataYX(dblVal, Rand(0, nDataPoints));
		}
		else
		{
			pChart->AddChartData(dblVal);
		}
	}

	CBCGPChartAxis* pYAxis = pChart->GetChartAxis(BCGP_CHART_Y_PRIMARY_AXIS);
	ASSERT_VALID(pYAxis);

	pYAxis->SetMaxZoomInFactor(100.); // don't allow to zoom Y axis too much (the default is 1000)
	pYAxis->ShowScrollBar(m_bShowScrollBar);

	CBCGPChartAxis* pXAxis = pChart->GetChartAxis(BCGP_CHART_X_PRIMARY_AXIS);
	ASSERT_VALID(pXAxis);

	pXAxis->SetFixedDisplayRange(0., nDataPoints);
	pXAxis->SetScrollRange(0., nDataPoints);
	pXAxis->ShowScrollBar(m_bShowScrollBar);

	pXAxis->SetMaxZoomInFactor(nDataPoints * 100); // allow more details on X axis

	pChart->SetDirty();
	pChart->Redraw();
}

void CChartHugeAverageDataView::OnUpdateZoom() 
{
	UpdateData();

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	pChart->EnableMouseTrackingMode(BCGPChartHitInfo::HIT_DIAGRAM);

	if (!m_bZoom)
	{
		pChart->SetAutoDisplayRange(TRUE, TRUE);
	}

	m_wndZoomType.EnableWindow(m_bZoom);
	m_wndZoom100.EnableWindow(m_bZoom);
	m_wndShowScrollBar.EnableWindow(m_bZoom);
	m_wndSelectionType.EnableWindow(m_bZoom && m_nZoomType == 2);
	m_wndSelectionLabel.EnableWindow(m_bZoom && m_nZoomType == 2);

	if (!m_bZoom)
	{
		pChart->SetZoomScrollConfig(BCGPChartMouseConfig::ZSO_NONE);

		m_strInfo.Empty();
		UpdateData(FALSE);
		return;
	}

	switch (m_nZoomType)
	{
	case 0:
		// Default - "Mouse wheel and pan" mode
		m_strInfo = _T("Use mouse wheel to zoom chart. If the chart is zoomed, you can pan it using left mouse button.");
		pChart->SetZoomScrollConfig(BCGPChartMouseConfig::ZSO_WHEEL_PAN);
		break;

	case 1:
		m_strInfo = _T("Left mouse button - zoom-in; Right mouse button - zoom out. Mouse wheel - scroll horizontally. Ctrl + mouse wheel - scroll vertically.");
		pChart->SetZoomScrollConfig(BCGPChartMouseConfig::ZSO_MAGNIFY);
		break;

	case 2:
		m_strInfo = _T("Select the chart area using left mouse button. Select with ALT key - zoom out. Mouse wheel - scroll horizontally. Ctrl + mouse wheel - scroll vertically.");
		
		BCGPChartFormatSelection::SelectionType selType = BCGPChartFormatSelection::ST_VERT_AND_HORZ_AXES;

		switch (m_nSelectionType)
		{
		case 0:
			selType = BCGPChartFormatSelection::ST_HORZ_AXIS_ONLY;
			break;

		case 1:
			selType = BCGPChartFormatSelection::ST_VERT_AXIS_ONLY;
			break;

		case 2:
			selType = BCGPChartFormatSelection::ST_VERT_AND_HORZ_AXES;
			break;
		}

		pChart->SetZoomScrollConfig(BCGPChartMouseConfig::ZSO_SELECT, selType);
		break;
	}

	UpdateData(FALSE);
	m_wndChart.SetFocus();
}

void CChartHugeAverageDataView::OnZoom100() 
{
	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	pChart->SetAutoDisplayRange(TRUE, TRUE);

	m_wndChart.SetFocus();
}

void CChartHugeAverageDataView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) 
{
	CBCGPChartExampleView::OnActivateView(bActivate, pActivateView, pDeactiveView);

	if (bActivate)
	{
		m_wndChart.SetFocus();
	}
}

void CChartHugeAverageDataView::OnUpdateScrollBars()
{
	UpdateData();

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	CBCGPChartAxis* pYAxis = pChart->GetChartAxis(BCGP_CHART_Y_PRIMARY_AXIS);
	ASSERT_VALID(pYAxis);

	pYAxis->ShowScrollBar(m_bShowScrollBar);

	CBCGPChartAxis* pXAxis = pChart->GetChartAxis(BCGP_CHART_X_PRIMARY_AXIS);
	ASSERT_VALID(pXAxis);

	pXAxis->ShowScrollBar(m_bShowScrollBar);

	pChart->SetDirty();
	pChart->Redraw();
}

LRESULT CChartHugeAverageDataView::OnMouseTrack(WPARAM /*wp*/, LPARAM lp)
{
	if (!m_bInteractiveMode)
	{
		return 0;
	}

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	CBCGPChartLongSeries* pSeries = DYNAMIC_DOWNCAST(CBCGPChartLongSeries, pChart->GetSeries(0));
	if (pSeries == NULL)
	{
		return 0;
	}

	BCGPChartHitInfo* pHitInfo = (BCGPChartHitInfo*)lp;
	CBCGPPoint pt = pHitInfo->m_ptHit;
	
	double dblValX = 0;
	double dblValY = 0;

	CBCGPPoint ptPrevPoint = m_ptValue;
	BOOL bMouseLeft = pt == CBCGPPoint(-1, -1);

	if (bMouseLeft || !pSeries->GetNearestScreenPoint(pt, m_ptValue, dblValX, dblValY))
	{
		m_ptValue.SetPoint(0, 0);
		m_pValueBox->m_strText = _T("Cursor is out of bounds.");
	}
	else
	{
		m_pValueBox->m_strText.Format(_T("X Value = %.2f\nY Value = %.2f"), dblValX, dblValY);
	}

	if (ptPrevPoint != m_ptValue || bMouseLeft)
	{
		pChart->Redraw();
	}

	return 0;
}

LRESULT CChartHugeAverageDataView::OnAfterDraw(WPARAM /*wp*/, LPARAM lp)
{
	if (!m_bInteractiveMode)
	{
		return 0;
	}

	CBCGPGraphicsManager* pGM = (CBCGPGraphicsManager*) lp;
	ASSERT_VALID(pGM);
	
	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	if (m_ptValue != CBCGPPoint())
	{
		CBCGPChartSeries* pSeries = pChart->GetSeries(0);
		
		BCGPSeriesColorsPtr colors;
		pSeries->GetColors(colors, 0);
		CBCGPRect rectAxisBounds = pSeries->GetAxesBoundingRect();	

		if (rectAxisBounds.PtInRect(m_ptValue))
		{
			CBCGPEllipse ellipse(m_ptValue, 5, 5);
			pGM->FillEllipse(ellipse, *colors.m_pBrElementLineColor);
		}
	}

	return 0;
}

LRESULT CChartHugeAverageDataView::OnAfterRecalcLayout(WPARAM /*wp*/, LPARAM /*lp*/)
{
	m_ptValue.SetPoint(0, 0);
	return 0;
}

void CChartHugeAverageDataView::OnInteractiveMode() 
{
	UpdateData();

	m_pValueBox->SetVisible(m_bInteractiveMode);
	m_wndChart.RedrawWindow();
}

void CChartHugeAverageDataView::OnSize(UINT nType, int cx, int cy) 
{
	CBCGPChartExampleView::OnSize(nType, cx, cy);
	
	if (m_wndChart.GetSafeHwnd() == NULL)
	{
		return;
	}

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	if (m_bShowScrollBar && pChart->GetScaleRatio() == CBCGPSize(1.0, 1.0))
	{
		pChart->RecalcMinMaxValues();
		
		CBCGPChartValue valMax = pChart->GetSeries(0)->GetMaxValue(CBCGPChartData::CI_Y);
		CBCGPChartValue valMin = pChart->GetSeries(0)->GetMinValue(CBCGPChartData::CI_Y);
		
		CBCGPChartAxis* pAxis = pChart->GetChartAxis(BCGP_CHART_Y_PRIMARY_AXIS);
		pAxis->SetScrollRange(valMin, valMax, TRUE);

		pChart->SetDirty(TRUE, TRUE);
	}
}
